builder: Add gtk_builder_set_closure_func()
authorBenjamin Otte <otte@redhat.com>
Thu, 21 Nov 2019 23:18:19 +0000 (00:18 +0100)
committerBenjamin Otte <otte@redhat.com>
Fri, 22 Nov 2019 07:13:16 +0000 (08:13 +0100)
This allows bindings and templates to setup a way to create closures.

docs/reference/gtk/gtk4-sections.txt
gtk/gtkbuilder.c
gtk/gtkbuilder.h
gtk/gtktypes.h

index c9fefcebf14cf13c48d7e2c0a29d8e964afc792e..522494a7a3ac9ecc99a8bbd976a2887b7100a611 100644 (file)
@@ -520,6 +520,7 @@ GTK_BUILDABLE_GET_IFACE
 <FILE>gtkbuilder</FILE>
 <TITLE>GtkBuilder</TITLE>
 GtkBuilder
+GtkBuilderClosureFunc
 GtkBuilderConnectFunc
 GtkBuilderError
 gtk_builder_new
@@ -546,6 +547,7 @@ gtk_builder_connect_signals_full
 gtk_builder_set_translation_domain
 gtk_builder_get_translation_domain
 gtk_builder_get_type_from_name
+gtk_builder_set_closure_func
 gtk_builder_value_from_string
 gtk_builder_value_from_string_type
 GTK_BUILDER_WARN_INVALID_CHILD_TYPE
index 5c00a5057087f52155d92a985458c5c55fb37917..fa2ef6bb0450e120c25b829575dd89eae99722c0 100644 (file)
@@ -249,6 +249,10 @@ typedef struct
   gchar *filename;
   gchar *resource_prefix;
   GType template_type;
+
+  GtkBuilderClosureFunc closure_func;
+  gpointer closure_data;
+  GDestroyNotify closure_destroy;
 } GtkBuilderPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkBuilder, gtk_builder, G_TYPE_OBJECT)
@@ -304,6 +308,9 @@ gtk_builder_finalize (GObject *object)
 {
   GtkBuilderPrivate *priv = gtk_builder_get_instance_private (GTK_BUILDER (object));
 
+  if (priv->closure_destroy)
+    priv->closure_destroy (priv->closure_data);
+
   g_clear_pointer (&priv->module, g_module_close);
 
   g_free (priv->domain);
@@ -1714,6 +1721,32 @@ gtk_builder_connect_signals (GtkBuilder *builder)
                                     NULL);
 }
 
+/**
+ * GtkBuilderClosureFunc:
+ * @builder: a #GtkBuilder
+ * @function_name: name of the function to create a closure for
+ * @swapped: if the closure should swap user data and instance
+ * @object: (nullable): object to use as user data for the closure
+ * @user_data: user data passed when setting the function
+ * @error: location for error when creating the closure fails
+ *
+ * Prototype of function used to create closures by @builder. It is meant
+ * for influencing how @function_name is resolved.
+ *
+ * This function is most useful for bindings and can be used with
+ * gtk_builder_set_closure_func() or gtk_widget_class_set_closure_func()
+ * to allow creating closures for functions defined in the binding's
+ * language.
+ *
+ * If the given @function_name does not match a function name or when the
+ * arguments cannot be supported by the bindings, bindings should return
+ * %NULL and set @error. Usually %GTK_BUILDER_ERROR_INVALID_FUNCTION will
+ * be the right error code to use.
+ *
+ * Returns: (nullable): a new #GClosure or %NULL when no closure could
+ *   be created and @error was set.
+ */
+
 /**
  * GtkBuilderConnectFunc:
  * @builder: a #GtkBuilder
@@ -2639,7 +2672,7 @@ gtk_builder_add_callback_symbols (GtkBuilder  *builder,
  *
  * This function is intended for possible use in language bindings
  * or for any case that one might be customizing signal connections
- * using gtk_builder_connect_signals_full()
+ * using gtk_builder_set_closure_func().
  *
  * Returns: (nullable): The callback symbol in @builder for @callback_name, or %NULL
  */
@@ -2658,6 +2691,38 @@ gtk_builder_lookup_callback_symbol (GtkBuilder  *builder,
   return g_hash_table_lookup (priv->callbacks, callback_name);
 }
 
+/**
+ * gtk_builder_set_closure_func: (skip)
+ * @builder: a #GtkBuilder
+ * @closure_func: (allow-none) function to call when creating
+ *     closures or %NULL to use the default
+ * @user_data: (nullable): user data to pass to @closure_func
+ * @user_destroy: destroy function for user data
+ *
+ * Sets the function to call for creating closures.
+ * gtk_builder_create_closure() will use this function instead
+ * of gtk_builder_create_cclosure().
+ *
+ * This is useful for bindings.
+ **/
+void
+gtk_builder_set_closure_func (GtkBuilder            *builder,
+                              GtkBuilderClosureFunc  closure_func,
+                              gpointer               user_data,
+                              GDestroyNotify         user_destroy)
+{
+  GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
+
+  g_return_if_fail (GTK_IS_BUILDER (builder));
+
+  if (priv->closure_destroy)
+    priv->closure_destroy (priv->closure_data);
+
+  priv->closure_func = closure_func;
+  priv->closure_data = user_data;
+  priv->closure_destroy = user_destroy;
+}
+
 static GClosure *
 gtk_builder_create_closure_for_funcptr (GtkBuilder *builder,
                                         GCallback   callback,
@@ -2710,12 +2775,17 @@ gtk_builder_create_closure (GtkBuilder *builder,
                             GObject    *object,
                             GError    **error)
 {
+  GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
+
   g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
   g_return_val_if_fail (function_name, NULL);
   g_return_val_if_fail (object == NULL || G_IS_OBJECT (object), NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-  return gtk_builder_create_cclosure (builder, function_name, swapped, object, error);
+  if (priv->closure_func)
+    return priv->closure_func (builder, function_name, swapped, object, priv->closure_data, error);
+  else
+    return gtk_builder_create_cclosure (builder, function_name, swapped, object, error);
 }
 
 /**
index fb192dc4a9a9f6b8415ad36f86f7e973297c9bc7..95b5b7642aff4d31290fbbff7d400d41562e4264 100644 (file)
@@ -115,6 +115,11 @@ GType        gtk_builder_get_type                (void) G_GNUC_CONST;
 GDK_AVAILABLE_IN_ALL
 GtkBuilder*  gtk_builder_new                     (void);
 
+GDK_AVAILABLE_IN_ALL
+void         gtk_builder_set_closure_func        (GtkBuilder    *builder,
+                                                  GtkBuilderClosureFunc closure_func,
+                                                  gpointer       user_data,
+                                                  GDestroyNotify user_destroy);
 GDK_AVAILABLE_IN_ALL
 gboolean     gtk_builder_add_from_file           (GtkBuilder    *builder,
                                                   const gchar   *filename,
index f11d389380600d9f4fc74827503e76f62d1862d4..05a2e7b5d8f6a546256428b377f618c1d86d0314 100644 (file)
@@ -51,7 +51,12 @@ typedef struct _GtkWidget              GtkWidget;
 typedef struct _GtkWidgetPath          GtkWidgetPath;
 typedef struct _GtkWindow              GtkWindow;
 
-
+typedef GClosure*       (* GtkBuilderClosureFunc)               (GtkBuilder             *builder,
+                                                                 const char             *function_name,
+                                                                 gboolean                swapped,
+                                                                 GObject                *object,
+                                                                 gpointer                user_data,
+                                                                 GError                **error);
 typedef void (*GtkBuilderConnectFunc) (GtkBuilder    *builder,
                                       GObject       *object,
                                       const gchar   *signal_name,